package cn.bqjr.eily.web.aspect;


import cn.bqjr.eily.core.annotation.DisableAutoLog;
import cn.bqjr.eily.core.log.LogAopEntity;
import cn.bqjr.eily.mybatis.spring.boot.entity.PageInfoVO;
import cn.bqjr.eily.mybatis.spring.boot.utils.PagingUtils;
import cn.bqjr.eily.web.utils.RUtils;
import cn.bqjr.eily.web.utils.WebLogAopUtils;
import com.alibaba.fastjson.JSON;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * 统一封装Controller返回信息
 */
@Aspect
@Component
public class RespPackagingAspect {

    private static final Logger logger = LoggerFactory.getLogger(RespPackagingAspect.class);

    @Autowired
    private HttpServletRequest request;

    @Pointcut("@within(org.springframework.web.bind.annotation.RestController) " +
            "|| @within(org.springframework.stereotype.Controller)")
    public void controllerMethodPointcut() {
    }

    @Around("controllerMethodPointcut()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        if (isProceed(pjp)) {
            return pjp.proceed();
        } else {
            PageInfoVO pageInfo = PagingUtils.initPageInfo(request);
            LogAopEntity entity = WebLogAopUtils.genarate(pjp, request);
            beforeExec(entity);
            Object obj = pjp.proceed();
            afterExec(obj, entity);
            return RUtils.ok(pageInfo, obj);
        }
    }

    /**
     * 执行前
     *
     * @param entity
     * @throws Exception
     */
    private void beforeExec(LogAopEntity entity) throws Exception {
        Map<String, Object> reqMap = WebLogAopUtils.getHttpRequestInfo(entity);
        logger.info("ControllerLog before：" + JSON.toJSONString(reqMap));
    }

    /**
     * 执行后
     *
     * @param returnObj
     * @param entity
     * @throws Exception
     */
    private void afterExec(Object returnObj, LogAopEntity entity) throws Exception {
        Map<String, Object> respMap = WebLogAopUtils.getResponseInfo(entity, returnObj);
        logger.info("ControllerLog after：" + JSON.toJSONString(respMap));
    }

    private boolean isProceed(ProceedingJoinPoint pjp) {
        Class cls = pjp.getTarget().getClass();
        if (cls.isAnnotationPresent(DisableAutoLog.class)) {
            return true;
        } else {
            MethodSignature signature = (MethodSignature) pjp.getSignature();
            Class methodReturnType = signature.getReturnType(); // 方法返回值类型
            Method method = signature.getMethod();
            if (Void.TYPE == methodReturnType
                    || method.isAnnotationPresent(DisableAutoLog.class)
                    || !WebLogAopUtils.isControllerAnnoPresent(method)) {
                return true;
            }
        }
        return false;
    }
}
